<script>
import isEqual from "lodash/isEqual";
import cloneDeep from "lodash/cloneDeep";
import request from "@/utils/request";
import { getObjectValueReduce } from "@/components/render/util";
import { getTableProps } from "./config";
import "./main";

export default {
  name: "UnTable",
  inheritAttrs: false,
  props: getTableProps(),
  data() {
    return {
      tData: this.value.data,
      currSpanMethod: this.spanMethod, // 当前单元格合并函数
    };
  },
  computed: {
    needApi() {
      return this.api && this.api.enable !== false;
    },
    columns() {
      return this.value.columns;
    },
    colSize() {
      return this.value.colSize;
    },
    rowSize() {
      return this.value.rowSize;
    },
  },
  watch: {
    api: {
      handler(val) {
        if (val && val.enable !== false) {
          this.setData();
        }
      },
      deep: true,
    },
    columns: {
      handler() {
        // 列配置变更时，刷新列表列
        this.$nextTick(() => {
          // 刷新列配置（对于动态修改属性、显示/隐藏列等场景下会用到）
          this.$refs.vxeTable.refreshColumn();
          // this.$refs.vxeTable.reloadData(this.tData);
        });
      },
      deep: true,
    },
    'value.data': {
      handler(val) {
        if (isEqual(val, this.tData)) {
          return;
        }
        this.tData = val;
      },
      deep: true
    },
    mergeType(val) {
      this.setMergeCols(val);
    },
    tData: {
      handler(tData) {
        if (this.needApi) {
          this.$emit('input', cloneDeep({ ...this.value, data: [], rowSize: tData && tData.length ? tData.length : 0 }));
        } else {
          this.$emit('input', cloneDeep({ ...this.value, data: tData }));
        }
      },
      deep: true,
    },
    editConfig: {
      handler(val) {
        // 表格编辑配置变更时，刷新列表列
        this.$nextTick(() => {
          this.$refs.vxeTable.refreshColumn();
        });
      },
      deep: true,
    },
  },
  created() {
    this.setData();
    this.setMergeCols(this.mergeType);
  },
  methods: {
    setData() {
      // 多个消费者
      if (this.needApi) {
        // 取接口信息时
        const { method, url, dataPath, params } = this.api;
        const options = {
          method,
          url,
        };
        if (method == "get") {
          options.params = params;
        } else {
          options.data = params;
        }
        request(options).then((resp) => {
          this.tData = getObjectValueReduce(resp, dataPath);
        });
      }
    },
    setMergeCols(mergeType) {
      if (mergeType === "row") {
        this.currSpanMethod = this.rowspanMethod;
      } else {
        this.currSpanMethod = this.spanMethod;
      }
    },
    // 通用行合并函数（将相同多列数据合并为一行）
    rowspanMethod({ row, _rowIndex, column, visibleData }) {
      let fields = this.rowMergedColFields || [];
      let cellValue = row[column.property];
      if (cellValue && fields.includes(column.property)) {
        let prevRow = visibleData[_rowIndex - 1];
        let nextRow = visibleData[_rowIndex + 1];
        if (prevRow && prevRow[column.property] === cellValue) {
          return { rowspan: 0, colspan: 0 };
        } else {
          let countRowspan = 1;
          while (nextRow && nextRow[column.property] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex];
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 };
          }
        }
      }
    },
    renderEditComponent(
      h,
      { componentName, value, col, /* row,  */ rowIndex }
    ) {
      let name = componentName;
      let config = {
        props: {
          value,
        },
        on: {
          input: (val) => {
            // 兼容内置组件数据格式
            const v = typeof val == "object" ? val.value : val;
            // row[col.field] = v;
            this.$set(this.tData[rowIndex], col.field, v);
          },
        },
      };
      switch (componentName) {
        case "el-textarea":
          name = "el-input";
          config.props.type = "textarea";
          break;

        default:
          break;
      }
      return h(name, config);
    },
    renderCols(h, cols, level = 0) {
      if (cols && cols.length) {
        return cols.map((col, idx) => {
          // 插槽
          const scopedSlots = {
            edit: ({ row, rowIndex /* ...rest */ }) => {
              // 如果列新增，数据中没有该字段，需要新增
              let fieldVal = row[col.field];
              if (fieldVal === undefined) {
                fieldVal = "";
                // 同步到源数据
                this.$set(this.tData[rowIndex], col.field, fieldVal);
              }
              return this.renderEditComponent(h, {
                componentName: col.editRender.componentName,
                value: fieldVal,
                col,
                row,
                rowIndex,
              });
            },
          };
          const { children, showOverflow, ...rest } = col;
          const overflowType = showOverflow !== 'tooltip' ? false : 'tooltip';
          return h(
            children && children.length ? "vxe-colgroup" : "vxe-column",
            {
              key: col.colId || level + "_" + idx, // 避免重名
              props: { ...rest, showOverflow: overflowType },
              scopedSlots: children && children.length ? {} : scopedSlots,
            },
            // {/* 嵌套多级表头 */}
            this.renderCols(h, children, level + 1)
          );
        });
      }
      return [];
    },
    renderFirstCol(h, col) {
      // 首列类型存在，首列不可编辑
      if (col && col.type) {
        // key 很关键，否则切换不生效
        return [h("vxe-column", { key: col.type, props: col })];
      }
      return [];
    },
  },
  render(h) {
    const { firstCol, ...restProps } = this.$props;
    const { tData, currSpanMethod } = this.$data;
    const { columns } = this;

    return h(
      "vxe-table",
      {
        ref: "vxeTable",
        props: {
          ...this.$props,
          data: tData,
          spanMethod: currSpanMethod,
        },
        class: "un-table-wrap",
      },
      [...this.renderFirstCol(h, firstCol), this.renderCols(h, columns, 0)]
    );
  },
};
</script>

<style lang="scss">
$border: 1px solid #bbb;

.un-table-wrap {
  line-height: 1.5;
  overflow-x: auto;
  &.vxe-editable .vxe-body--column.col--edit.col--actived {
    height: auto;
    .vxe-cell {
      max-height: inherit;
    }
  }
}
</style>
